#define LpcPortName L"\\SinApi"
#define LpcCommEvent L"\\LpcCommEvent"
#define LpcEventName L"\\LpcSyncEvent"

//this will be DWORD NTAPI SinSrvClientConnectServer(void)
DWORD NTAPI SinSrvClientConnectServer(void)
{
	SECURITY_QUALITY_OF_SERVICE SecurityQos = {0};
	REMOTE_PORT_VIEW ServerView = {0};
	UNICODE_STRING Unicode = {0};
	ANSI_STRING Ansi = {0};
	LARGE_INTEGER SectionSize = {0x4096};
	PORT_VIEW ClientView = {0};
	OBJECT_ATTRIBUTES oa = {0};
	void *RecvMessage	= 0;
	void *ReplyMessage = 0;
	SIN_API_MESSAGE ApiRecvMessage;
	SIN_API_MESSAGE ApiReplyMessage;
	SinSrvClientApiWithParameter pClientApi = 0;
	SinSrvClientApi ClientApi = 0;
    NTSTATUS Status = STATUS_SUCCESS;
    HANDLE SectionHandle = INVALID_HANDLE_VALUE;
    HANDLE PortHandle = INVALID_HANDLE_VALUE;
	ULONG ThreadId = {0};
	CLIENT_ID Cid = {0};
	LONG EventState = 0;
	ULONG MaxMsg = 0;
    __try
    {
		CreateThread(0,0,(LPTHREAD_START_ROUTINE)Sleep,(PVOID)0x10000,0,&MaxMsg);
		CreateThread(0,0,(LPTHREAD_START_ROUTINE)Sleep,(PVOID)0x10000,0,&MaxMsg);
		Status = NtCreateSection(&SectionHandle,SECTION_ALL_ACCESS,NULL,&SectionSize,PAGE_EXECUTE_READWRITE,SEC_COMMIT,0);
        if(!NT_SUCCESS(Status))
		{
            __leave;
		}
		RtlInitUnicodeString(&Unicode, LpcPortName);
		SecurityQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
        SecurityQos.ImpersonationLevel = SecurityImpersonation;
        SecurityQos.EffectiveOnly = FALSE;
        SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
		ClientView.Length        = sizeof(ClientView);
        ClientView.SectionHandle = SectionHandle;
        ClientView.SectionOffset = 0;
        ClientView.ViewSize      = 0x4096;
        ServerView.Length        = sizeof(REMOTE_PORT_VIEW);
        Status = NtConnectPort(&PortHandle,&Unicode,&SecurityQos,&ClientView,&ServerView,0,NULL,NULL);
        if(Status != 0)
		{
            __leave;
		}
		RecvMessage = RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SIN_API_MESSAGE));
		ReplyMessage = RtlAllocateHeap(RtlProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SIN_API_MESSAGE));
		ApiRecvMessage = *(SIN_API_MESSAGE*)RecvMessage;
		ApiReplyMessage = *(SIN_API_MESSAGE*)ReplyMessage;
WaitForServer:
		InitializeSinApiMessage(&ApiReplyMessage,sizeof(SIN_API_MESSAGE),LPC_NEW_MESSAGE,SIN_SUSPEND_CLIENT);
		Status = NtRequestWaitReplyPort(PortHandle,(PORT_MESSAGE*)&ApiReplyMessage,(PORT_MESSAGE*)&ApiRecvMessage);
		switch(ApiRecvMessage.Status)
		{
			case 0://do nothing wait for further instruction ...
			{
				goto WaitForServer;
			}							
			case 1://execute Api Mapped into client process by server
			{
				if(ApiRecvMessage.StartAddress == 0)
				{
					goto WaitForServer;
				}
				else
				{
					if(ApiRecvMessage.Data != 0)
					{
						pClientApi = (SinSrvClientApiWithParameter)ApiRecvMessage.StartAddress;
						pClientApi((void*)ApiRecvMessage.Data);
						goto WaitForServer;
					}
					else
					{
						ClientApi = (SinSrvClientApi)ApiRecvMessage.StartAddress;
						ClientApi();
						goto WaitForServer;
					}
				}
			}
		 }
	}
    __except(1)
    {
		if(PortHandle != INVALID_HANDLE_VALUE)
		{
            NtClose(PortHandle);
		}
        if(SectionHandle != INVALID_HANDLE_VALUE)
		{        
			NtClose(SectionHandle);
		}
	}
    return 0;
}
